;; bits of the robot problem ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; DATA DEFINITIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; A Direction is one of: ;; -- "north" ;; -- "east" ;; -- "west" ;; -- "south" ;; TEMPLATE ;; dir-fn : Direction -> ?? ;; (define (dir-fn d) ;; (cond ;; [(string=? d "north") ...] ;; [(string=? d "east") ...] ;; [(string=? d "south") ...] ;; [(string=? d "west") ...])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define-struct robot (x y dir)) ;; A Robot is a (make-robot Number Number Direction) ;; INTERP: ;; x and y are the position of the robot in the space ;; dir is the direction the robot is facing ;; TEMPLATE ;; robot-fn : Robot -> ?? ;; (define (robot-fn r) ;; (... (robot-x r) (robot-y r) (robot-dir r))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Let's look at several versions of robot-left ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; robot-left (version 0, incorrect) ;; robot-left : Robot -> Robot ;; GIVEN: a Robot ;; RETURNS: a Robot like the given one, but turned 90 degrees to the ;; left ;; STRATEGY: structural decomp on r : Robot (define (robot-left r) (cond [(robot-north? r) (make-robot (robot-x r) (robot-y r) "west")] [(robot-east? r) (make-robot (robot-x r) (robot-y r) "north")] [(robot-south? r) (make-robot (robot-x r) (robot-y r) "east")] [(robot-west? r) (make-robot (robot-x r) (robot-y r) "south")]) ;; Yikes! That's a great big honking pile of code! ;; This is __way__ too complicated for a single functional ;; composition. ;; You need to do something better. ;; What this code is trying to do is to do a decomposition both on the ;; robot and on its direction. ;; You are only allowed to do decomposition on one thing at a time. ;; So you need to do this in two steps. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; robot-left (version 1) ;; To do this, we need to analyze a robot AND its direction (2 struct ;; decomps!) ;; robot-left : Robot -> Robot ;; GIVEN: a Robot ;; RETURNS: a Robot like the given one, but turned 90 degrees to the ;; left ;; STRATEGY: struct decomp on Robot (define (robot-left r) (robot-left-helper (robot-x r) (robot-y r) (robot-dir r))) ;; robot-left-helper : Number Number Direction -> Robot ;; GIVEN: the coordinates and direction of some robot ;; RETURNS: a Robot like the original, but turned 90 degrees to the ;; left. ;; STRATEGY: struct decomp on Direction (define (robot-left-helper x y dir) (cond [(string=? d "north") (make-robot x y "west")] [(string=? d "east") (make-robot x y "north")] [(string=? d "south") (make-robot x y "east")] [(string=? d "west") (make-robot x y "south")])) ;; IT'S JUST LIKE THE TRAFFIC LIGHT! ;; Here I couldn't think of a better name than robot-left-helper, but ;; you should try ;; If you were doing something complicated here, you can and should ;; call another layer of helpers. ;; The purpose statement, like: ;; GIVEN: the coordinates and direction of _some robot_ ;; tells you what you've figured out before you got to this help ;; function. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; robot-left (version 2) ;;; Hmm, all these functions end up doing (make-robot x y ;;; ). With a little cleverness, we can take advantage of ;;; this fact. ;; strategy: struct decomp on r : Robot (define (robot-left r) (make-robot (robot-x r) (robot-y r) (direction-left (robot-dir r)))) ;; direction-left : Direction -> Direction ;; GIVEN: A Direction ;; RETURNS: the Direction 90 degrees to the left of the given one ;; STRATEGY: Struct decomp on d : Direction (define (direction-left d) (cond [(string=? d "north") "west"] [(string=? d "east") "north"] [(string=? d "south") "east"] [(string=? d "west") "south"])) ;; We'll have a lot more to say about this when we talk about ;; Generalization in Week 5 (next week). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;